package com.atguigu.locks.service;

import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author : leimingchao
 * @date Date : 2021年11月28日 10:04
 */
@Service
public class RedissonLockService {

    @Autowired
    private RedissonClient redissonClient;

    @Qualifier(value = "mainThreadPoolExecutor")
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Qualifier(value = "otherThreadPoolExecutor")
    @Autowired
    private ThreadPoolExecutor otherThreadPoolExecutor;

    private String hello = "hello";

    public void test() {
        // threadPoolExecutor.submit((new Thread(() -> {
        //     System.out.println("基本信息");
        // })));

        CompletableFuture.supplyAsync(() -> {
            return "";
        },threadPoolExecutor).whenComplete((r,e) -> {
            System.out.println("处理结果：" + r);
            System.out.println("处理异常：" + e);
        });
    }

    public boolean lock() {

        RLock lock = redissonClient.getLock("lock");
        //默认是阻塞的
        // lock.lock();

        //等待100秒内只要能获取到锁，这个锁就10秒超时
        //lock.tryLock(100, 10, TimeUnit.SECONDS);

        //lock.tryLock():是非阻塞的，尝试一下，拿不到就算了

        lock.lock();
        System.out.println("第一次锁");
        lock.lock();
        System.out.println("第二次锁");
        lock.lock();
        System.out.println("第三次锁");
        //这个线程的任意期间都要获取这把锁，是直接使用的


        return lock.tryLock();

        //哪个线程加的锁一定要在这个线程解锁

        //加锁
        //业务
        //解锁
    }

    /**
     * 1.两个服务及两个以上服务操作相同数据，如果涉及读写
     *   读加读锁，写加写锁
     */
    public void unlock() {
        // RLock lock = redissonClient.getLock("lock");
        // lock.unlock();

        //错误的场景
        // RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("helloValue");
        // RLock readLock = readWriteLock.readLock();
        // RLock writeLock = readWriteLock.writeLock();
        // //修改一号记录
        // readLock.lock();
        // //修改
        // writeLock.lock();
    }

    /**
     * 写锁是一个排他锁(独占锁)
     * 读锁是一个共享锁
     * 有写锁情况下，写锁以后的读都不可以，只有写锁释放才能读。
     * 多个写，有写锁存在，就必须竞争写锁。
     * @return
     */
    public String read() {
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("helloValue");
        RLock readLock = readWriteLock.readLock();
        readLock.lock();
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String a = hello;
        readLock.unlock();
        return a;
    }

    public String write() {
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("helloValue");
        RLock writeLock = readWriteLock.writeLock();
        writeLock.lock();
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        hello = UUID.randomUUID().toString();
        writeLock.unlock();
        return hello;
    }

    public Boolean park() {
        RSemaphore rSemaphore = redissonClient.getSemaphore("tcc");
        try {
            rSemaphore.acquire();
            return true;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return false;
    }

    public Boolean release() {
        RSemaphore rSemaphore = redissonClient.getSemaphore("tcc");
        rSemaphore.release();
        return true;
    }

    public Boolean go() {
        RCountDownLatch countDownLatch = redissonClient.getCountDownLatch("num");
        countDownLatch.countDown();
        System.out.println("溜了.....");
        return true;
    }

    public Boolean lockDoor() {
        RCountDownLatch countDownLatch = redissonClient.getCountDownLatch("num");
        countDownLatch.trySetCount(10);
        try {
            //等大家走完
            countDownLatch.await();
            System.out.println("我要锁门");
            return true;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return false;
    }
}
